﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DDD.Core;

using FloatComparer = DDDTest.Helper.FloatComparer;

namespace DDDTest.Core {
    [TestClass]
    public class TestSkinnedMesh {
        [TestMethod]
        public void Test_New1 () {
            var msh = new SkinnedMesh ();

            Assert.AreEqual (1, msh.SubmeshCount);
            Assert.AreEqual (0, msh.BoneCount);
        }

        [TestMethod]
        public void Test_New2 () {
            var msh = new SkinnedMesh (2);

            Assert.AreEqual (2, msh.SubmeshCount);
            Assert.AreEqual (0, msh.BoneCount);
        }

        [TestMethod]
        public void Test_SetBones () {
            var msh = new SkinnedMesh (2);
            var nod = new Node ();
            nod.Attach (msh);

            var bone1 = new Node ();
            var bone2 = new Node ();
            var bone3 = new Node ();

            nod.AddChild (bone1);
            bone1.AddChild (bone2);
            bone1.AddChild (bone3);

            bone2.SetTranslation (1, 1, 1);
            bone3.SetTranslation (2, 2, 2);

            msh.SetBones (new[] { bone1, bone2, bone3 });

            Assert.AreEqual (3, msh.BoneCount);
            Assert.AreEqual (bone1, msh.GetBone (0));
            Assert.AreEqual (bone2, msh.GetBone (1));
            Assert.AreEqual (bone3, msh.GetBone (2));

            var expected1 = new Matrix4x4 (1, 0, 0, 0,
                                           0, 1, 0, 0,
                                           0, 0, 1, 0,
                                           0, 0, 0, 1);
            var expected2 = new Matrix4x4 (1, 0, 0, -1,
                                           0, 1, 0, -1,
                                           0, 0, 1, -1,
                                           0, 0, 0, 1);
            var expected3 = new Matrix4x4 (1, 0, 0, -2,
                                           0, 1, 0, -2,
                                           0, 0, 1, -2,
                                           0, 0, 0, 1);

            Assert.AreEqual (expected1, msh.GetInvBindPoseMatrix (0));
            Assert.AreEqual (expected2, msh.GetInvBindPoseMatrix (1));
            Assert.AreEqual (expected3, msh.GetInvBindPoseMatrix (2));
        }

        [TestMethod]
        public void Test_References () {
            var msh = new SkinnedMesh ();
            var nod = new Node ();
            nod.Attach (msh);

            var bone1 = new Node ();
            var bone2 = new Node ();
            var bone3 = new Node ();
            nod.AddChild (bone1);
            bone1.AddChild (bone2);
            bone1.AddChild (bone3);

            msh.SetBones (new[] { bone1, bone2, bone3 });

            var objs = msh.References;

            Assert.AreEqual (3, objs.Count ());
            Assert.AreEqual (true, objs.All (x => x != null));
        }

        [TestMethod]
        public void Test_Find () {
            var msh = new SkinnedMesh ();
            var nod = new Node ();
            nod.Attach (msh);

            var bone1 = new Node ();
            var bone2 = new Node ();
            var bone3 = new Node ();
            nod.AddChild (bone1);
            bone1.AddChild (bone2);
            bone1.AddChild (bone3);

            msh.SetBones (new[] { bone1, bone2, bone3 });


            bone1.UserID = 101;
            bone2.UserID = 102;
            bone3.UserID = 103;
            nod.UserID = 104;
            msh.UserID = 105;

            Assert.AreEqual (bone1, msh.Find (101));
            Assert.AreEqual (bone2, msh.Find (102));
            Assert.AreEqual (bone3, msh.Find (103));
            Assert.AreEqual (null, msh.Find (104));
            Assert.AreEqual (msh, msh.Find (105));
        }
    }
}
